package com.xci.platform.helper;

import cn.hutool.core.util.StrUtil;
import com.xci.platform.core.Constant;
import com.xci.platform.core.Tree;
import com.xci.platform.core.TreeNode;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 树形结构操作类
 *
 * @author 吕艳阳
 */
public class TreeHelper {

    /**
     * 生成路径字符串
     *
     * @param parentPath 上级路径
     * @param index      序号
     * @return 返回新创建的排序路径
     */
    public static String buildPath(String parentPath, Integer index) {
        if (StringHelper.isBlank(parentPath)) {
            parentPath = Constant.Empty;
        }
        return parentPath + StrUtil.fillBefore(index.toString(), '0', Constant.PathLength);
    }

    /**
     * 树形查询条件
     *
     * @param list       数据源
     * @param resultList 结果列表
     */
    public static List<?> filter(List<? extends Tree> list, List resultList) {
        // Predicate<? super TreeModel> predicate
        // List resultList = list.stream().filter(predicate).collect(Collectors.toList());
        if (resultList == null || resultList.size() == 0) return resultList;
        List<Tree> treeList = new ArrayList<>();
        for (Object entity : resultList) {
            Tree model = (Tree) entity;
            //先把自己加入进来
            treeList.add(model);
            //向上查询
            String pid = model.getParentId();
            getParentsCore(list, treeList, pid);
        }
        treeList.sort(Comparator.comparing(Tree::getPath));
        return treeList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 获取指定节点的所有父节点
     *
     * @param list    数据源
     * @param id      指定节点id
     * @param hasSelf 是否包含自身
     */
    public static List<?> getParents(List<? extends Tree> list, String id, boolean hasSelf) {
        Optional<? extends Tree> entityOptional = list.stream().filter(p -> p.getId().equals(id)).findFirst();
        if (!entityOptional.isPresent()) return new ArrayList<>();

        Tree entity = entityOptional.get();
        List<Tree> storeList = new ArrayList<>();
        if (hasSelf) {
            storeList.add(entity);
        }
        String pid = entity.getParentId();
        getParentsCore(list, storeList, pid);
        storeList.sort(Comparator.comparing(Tree::getPath));
        return storeList;
    }

    private static void getParentsCore(List<? extends Tree> list, List<Tree> storeList, String pid) {
        while (true) {
            if (StringHelper.isBlank(pid) && pid.equals(Constant.RootNodeId)) break;
            final String parentId = pid;
            Optional<? extends Tree> parentOptional = list.stream().filter(p -> p.getId().equals(parentId)).findFirst();
            if (!parentOptional.isPresent()) break;

            Tree parent = parentOptional.get();
            storeList.add(parent);
            pid = parent.getParentId();
        }
    }

    /**
     * 获取指定节点的所有子节点
     *
     * @param list    数据源
     * @param id      指定节点id
     * @param hasSelf 是否包含自身
     */
    public static List<?> getChilds(List<? extends Tree> list, String id, boolean hasSelf) {
        Optional<? extends Tree> entityOptional = list.stream().filter(p -> p.getId().equals(id)).findFirst();
        if (!entityOptional.isPresent()) return new ArrayList<>();

        Tree entity = entityOptional.get();
        List<Tree> storeList = new ArrayList<>();
        if (hasSelf) {
            storeList.add(entity);
        }
        getChildsCore(list, storeList, entity);
        return storeList;
    }

    private static void getChildsCore(List<? extends Tree> entityList, List<Tree> storeList, Tree entity) {
        String id = entity.getId();
        List<Tree> data = entityList.stream().filter(p -> p.getParentId().equals(id)).collect(Collectors.toList());
        if (data.size() <= 0) return;
        for (Tree item : data) {
            storeList.add(item);
            getChildsCore(entityList, storeList, item);
        }
    }

    /**
     * 转为节点列表
     *
     * @param treeModelList 模型列表
     */
    public static List<TreeNode> toTreeNodeList(List<? extends Tree> treeModelList) {
        List<TreeNode> nodeList = new ArrayList<>();
        for (Tree item : treeModelList) {
            TreeNode node = new TreeNode();
            node.setId(item.getId());
            node.setPid(item.getParentId());
            node.setText(item.getName());
            node.setSpell(item.getSpell());
            node.setLeaf(item.getLeaf());
            nodeList.add(node);
        }
        return nodeList;
    }
}
